package com.liruo.srpingframework.dataaccess.transaction.propagation;

import com.liruo.srpingframework.dataaccess.transaction.TransactionEntity;
import com.liruo.srpingframework.dataaccess.transaction.TransactionEntityRepository;
import javax.annotation.Resource;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

@Service
public class PropagationRequestOrNewService {

  @Resource
  TransactionEntityRepository repository;

  @Transactional
  public void m1REQUESTED(Propagation propagation) {
    PropagationRequestOrNewService proxy = (PropagationRequestOrNewService)AopContext.currentProxy();
    if(propagation == null){
      //common use
      proxy.m2();
      return;
    }
    try {
      if (propagation == Propagation.REQUIRED) {
        //异常被捕获,但是m2REQUESTED的修改并没有进行回滚, 因此表中一定有1行数据, 执行完m1REQUESTED后才在提交时,
        // 因为执行完m2REQUESTED被设置为GlobalRollbackOnly, 因此去rollback,但是是unexpectedRollback的, 因此抛出UnexpectedRollbackException
        proxy.m2REQUESTED();
        Assert.isTrue(repository.count() == 1, "proxy.m2REQUESTED() has not add 1 row");
      } else {
        //在一个新的事务中执行, 因此执行完就commit, 有错误也进行回滚
        proxy.m2REQUESTED_NEW();
      }
    } catch (Exception e) {
    }
  }
  @Transactional
  public void m2() {
    repository.save(new TransactionEntity(
        null,
        PropagationRequestOrNewService.class.getSimpleName() + "#m2"));
    throw new RuntimeException("m2");
  }
  @Transactional
  public void m2REQUESTED() {
    repository.save(new TransactionEntity(
        null,
        PropagationRequestOrNewService.class.getSimpleName() + "#m2REQUESTED"));
    throw new RuntimeException("m2REQUESTED");
  }

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void m2REQUESTED_NEW() {
    repository.save(new TransactionEntity(
        null,
        PropagationRequestOrNewService.class.getSimpleName() + "#m2REQUESTED_NEW"));
    throw new RuntimeException("m2REQUESTED_NEW");
  }
}
